﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CsharpWpfManual
{


    public partial class LineChartControl : UserControl
    {


        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Title.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(LineChartControl), new PropertyMetadata(""));





        public int MaxValue
        {
            get { return (int)GetValue(MaxValueProperty); }
            set
            {
                SetValue(MaxValueProperty, value);
                this.InvalidateVisual();

            }
        }

        // Using a DependencyProperty as the backing store for MaxValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaxValueProperty =
            DependencyProperty.Register("MaxValue", typeof(int), typeof(LineChartControl),
                new FrameworkPropertyMetadata(250, new PropertyChangedCallback(MaxValueChangedCallback)));

        public static void MaxValueChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as LineChartControl).MaxValue = (int)e.NewValue;
            (sender as LineChartControl).UpdateKD();
        }



        public IEnumerable<object> ItemSource
        {
            get { return (IEnumerable<object>)GetValue(ItemSourceProperty); }
            set { SetValue(ItemSourceProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ItemSource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ItemSourceProperty =
            DependencyProperty.Register("ItemSource", typeof(IEnumerable<object>), typeof(LineChartControl),
                new FrameworkPropertyMetadata(null));







        public string DisplayMemberMsg
        {
            get { return (string)GetValue(DisplayMemberMsgProperty); }
            set { SetValue(DisplayMemberMsgProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DisplayMemberMsg.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisplayMemberMsgProperty =
            DependencyProperty.Register("DisplayMemberMsg", typeof(string), typeof(LineChartControl), new PropertyMetadata("Name"));




        public string DisplayMemberValue
        {
            get { return (string)GetValue(DisplayMemberValueProperty); }
            set { SetValue(DisplayMemberValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DisplayMemberValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisplayMemberValueProperty =
            DependencyProperty.Register("DisplayMemberValue", typeof(string), typeof(LineChartControl), new PropertyMetadata("Value"));




        public string DisplayGroupByPath
        {
            get { return (string)GetValue(DisplayGroupByPathProperty); }
            set { SetValue(DisplayGroupByPathProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DisplayGroupByPath.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisplayGroupByPathProperty =
            DependencyProperty.Register("DisplayGroupByPath", typeof(string), typeof(LineChartControl), new PropertyMetadata(null));





        public LineChartControl()
        {
            InitializeComponent();
            DrawYSegment();

            //DrawXsegment();//不能放再这里，里面用到了MaxValue。这个值在XAML中赋值了，但在构造函数中还没有值，在load中才有值

        }


        private Point StartPoint = new Point(100, 300);
        private int xWidth = 600;
        private int xSegmentCount = 7;


        private int yHeight = 250;
        private int ySegmentCount = 25; //Y轴的总刻度分段， 
        private int SingleYSegmentLentgh//Y轴刻度线间隔
        {
            get { return yHeight / ySegmentCount; }
        }
        private int SingleYSegmentValue//Y轴刻度线单位值
        {
            get
            {
                return MaxValue / ySegmentCount;
            }
        }


        private int InnerLineWdith = 10;


        /// <summary>
        /// 画Y轴的刻度线
        /// </summary>
        private void DrawYSegment()
        {
            //纵轴坐标，从下往上，(100,300) -> (100,50) 总长 250,分成25段。每段长10。
            //类推，从下往上，坐标。依次为 [(95,300)(105,300)][(95,290)(105,290)]......

            double StartPointX = StartPoint.X;
            double x1 = StartPointX - InnerLineWdith / 2;
            double x2 = StartPointX;


            double PointY = StartPoint.Y;


            for (int i = 0; i <= ySegmentCount; i++)
            {
                int l = 0;
                if ((i) % 5 == 0)//逢5 画 刻度的值，且刻度线长度+5
                {
                    l = 5;
                    //< Label Width = "60"  VerticalContentAlignment = "Center" HorizontalContentAlignment = "Right" 
                    // Height = "30"  Margin = "20,245,0,0" HorizontalAlignment = "Left" > 50 </ Label >
                    Label label = new Label()
                    {
                        Width = 60,
                        VerticalContentAlignment = VerticalAlignment.Center,
                        HorizontalContentAlignment = HorizontalAlignment.Right,
                        Height = 30,
                        //Content= SingleYSegmentValue*(i)
                    };
                    Ylbls.Add(label);
                    double x = StartPointX - (InnerLineWdith / 2) - 60 - 20;  //x坐标值=StartPointX-（InnerLineWdith / 2）-label宽度 -20
                    double y = PointY - 30 / 2;//label y坐标
                    Canvas.SetTop(label, y);
                    Canvas.SetLeft(label, x);
                    canvas.Children.Add(label);

                }

                Point p1 = new Point(x1 - l, PointY);
                Point p2 = new Point(x2, PointY);
                AddYSingleLine(p1, p2);
                PointY -= SingleYSegmentLentgh;
            }


        }
        private List<Label> Ylbls = new List<Label>();
        public void UpdateKD()
        {
            var footer = SingleYSegmentValue * 5;
            foreach (var item in Ylbls)
            {
                item.Content = Ylbls.IndexOf(item) * footer;
            }
        }

        private void AddYSingleLine(Point p1, Point p2)
        {
            PathFigure pathFigure = new PathFigure();
            pathFigure.StartPoint = p1;
            pathFigure.Segments.Add(new LineSegment(p2, true));
            Yline.Figures.Add(pathFigure);
        }



        private object GetValueFromObject(object obj, string propName)
        {
            Type type = obj.GetType();

            PropertyInfo property = type.GetProperty(propName);

            return property.GetValue(obj);

        }

        private Dictionary<string, Point> dicSecumentPoint;
        private void DrawXsegment(List<string> segments,out Dictionary<string,Point> dicSecumentPoint )
        {
            dicSecumentPoint = new Dictionary<string, Point>();
            if (segments == null)
            {
                return;
            }

            //横轴坐标，70长度为一段，
            double StartPointX = StartPoint.X;
            double PointY1 = StartPoint.Y;
            double PointY2 = StartPoint.Y + 10;

            //为支持重复跟新，需要支持重复画
            {
                xline.Figures.Clear();
                foreach (var lbl in lstLabel)
                {
                    canvas.Children.Remove(lbl);
                }
                lstLabel.Clear();


            }

            foreach (var segment in segments)
            {

                try
                {
                  
                    Point p1 = new Point(StartPointX, PointY1);
                    Point p2 = new Point(StartPointX, PointY2);
                    AddXSingleLine(p1, p2);
                    StartPointX += 70;//间隔为70
                    dicSecumentPoint.Add(segment, new Point(StartPointX - 70 / 2, PointY1));

                    //bar的宽度为30，那么bar左右间隔为20,bar的右下角坐标为StartPointX-20 ,PointY1. 
                    //那么 左上角坐标为 StartPointX-20 -30,PointY1-barheight;
                    Label labelBottom = new Label()
                    {
                        Width = 70,
                        VerticalContentAlignment = VerticalAlignment.Bottom,
                        HorizontalContentAlignment = HorizontalAlignment.Center,
                        Height = 40,
                        Content = segment
                    };
                    Canvas.SetTop(labelBottom, p1.Y);
                    Canvas.SetLeft(labelBottom, p1.X);
                    canvas.Children.Add(labelBottom);
                    lstLabel.Add(labelBottom);

                }
                catch (Exception ex)
                {

                    MessageBox.Show(ex.Message);
                }


            }

            XMainline.EndPoint = new Point(StartPointX, 300);
            gd.Width = StartPointX + 100;
        }

        List<Path> lines = new List<Path>();

        public void DrawSingleLine(IEnumerable<object> Items,Brush color,string name)
        {
            if (Items == null)
            {
                return;
            }

            //横轴坐标，70长度为一段，
            double StartPointX = StartPoint.X;
            double PointY1 = StartPoint.Y;
            double PointY2 = StartPoint.Y + 10;

            //
            Path line = new Path() { Stroke = color, StrokeThickness = 1, SnapsToDevicePixels = true };
            canvas.Children.Add(line);
            PathGeometry pg = new PathGeometry();
            line.Data = pg;
            lines.Add(line);

            PathFigure pathFigure = new PathFigure();
            pg.Figures.Add(pathFigure);
            //< Ellipse Width = "10" Height = "10" Fill = "Blue" Margin = "0,0,0,0" ></ Ellipse >      
            //< Label Content = "陈哲栋" Margin = "0,0,20,0" VerticalContentAlignment = "Center" ></ Label >
            sp.Children.Add(new Ellipse() { Width=10,Height=10,Fill=color });
            sp.Children.Add(new Label() { Margin=new Thickness(0,0,20,0),VerticalContentAlignment= VerticalAlignment.Center,Content= name });

            foreach (var item in Items)
            {

                try
                {

                    string displaymsg = GetValueFromObject(item, DisplayMemberMsg).ToString();
                    if(dicSecumentPoint.TryGetValue(displaymsg,out Point Zeropoint))
                    {
                        double value = (double)GetValueFromObject(item, DisplayMemberValue);
                        double barheight = value / SingleYSegmentValue * SingleYSegmentLentgh;//总长度yHeight
                                                                                              //lineGP.Children.Add(new RectangleGeometry(new Rect(StartPointX - 20 - 30, PointY1 - barheight, 30, barheight)));
                        double x = Zeropoint.X;
                        double y = Zeropoint.Y - barheight;
                        if (dicSecumentPoint.First().Key== displaymsg)//首个点
                        {
                            pathFigure.StartPoint = new Point(x, y);
                        }
                        else
                        {
                            pathFigure.Segments.Add(new LineSegment(new Point(x, y), true));
                        }
                    }



                    
                }
                catch (Exception ex)
                {

                    MessageBox.Show(ex.Message);
                }
            }
        }

        private List<Label> lstLabel = new List<Label>();

        private void AddXSingleLine(Point p1, Point p2)
        {
            PathFigure pathFigure = new PathFigure();
            pathFigure.StartPoint = p1;
            pathFigure.Segments.Add(new LineSegment(p2, true));
            xline.Figures.Add(pathFigure);
        }


        private int index=0;
        /// <summary>
        /// 先就这么土土的写着吧
        /// </summary>
        /// <returns></returns>
        private Brush GetNextBrush()
        {
            switch (index++)
            {
                case 0: return Brushes.Red;
                case 1: return Brushes.Blue;
                case 2: return Brushes.Gray;
                case 3: return Brushes.Yellow;
                case 4: return Brushes.DarkOrange;
                case 5: return Brushes.Pink;
                default:
                    return  Brushes.Beige;
            }
        }


        private void canvas_Loaded(object sender, RoutedEventArgs e)
        {
            UpdateKD();
            var Items= new List<BarChartItem>()
                {
                    new BarChartItem(){name="陈傻傻",money=3500,year=2012 },
                    new BarChartItem(){name="陈傻傻",money=4300,year=2013  },
                    new BarChartItem(){name="陈傻傻",money=8100,year=2014  },
                    new BarChartItem(){name="陈傻傻",money=7000,year=2015  },
                    new BarChartItem(){name="陈傻傻",money=4600,year=2016 },
                    new BarChartItem(){name="陈傻傻",money=7700,year=2017  },
                    new BarChartItem(){name="陈傻傻",money=6000,year=2018  },

                    new BarChartItem(){name="周笨笨",money=4500,year=2012 },
                    new BarChartItem(){name="周笨笨",money=6300,year=2013  },
                    new BarChartItem(){name="周笨笨",money=7100,year=2014  },
                    new BarChartItem(){name="周笨笨",money=5000,year=2015  },
                    new BarChartItem(){name="周笨笨",money=8600,year=2016 },
                    new BarChartItem(){name="周笨笨",money=6700,year=2017  },
                    new BarChartItem(){name="周笨笨",money=8000,year=2018  }
                };
            DrawXsegment(new List<string>() { "2012", "2013" , "2014" , "2015" , "2016" , "2017" , "2018"  },out  dicSecumentPoint);
            foreach (var aaa in Items.GroupBy((item) => { return item.name; }))
            {
                DrawSingleLine(aaa, GetNextBrush(),aaa.Key);

            }

        }
    }

}
